﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Xml;
using Community.DynamicsCrmWebResourceTool.Models;

namespace Community.DynamicsCrmWebResourceTool.UI
{
    public partial class MapAndPublishForm : Form
    {
        internal string ProjectPath { get; set; }
        internal string SelectedFileName { get; set; }

        private Settings settings;

        private List<Solution> Solutions { get; set; }
        private Solution SelectedSolution { get; set; }

        public MapAndPublishForm()
        {
            InitializeComponent();

            settings = new Settings();
        }

        private void btnConnect_Click(object sender, EventArgs e)
        {
            if (lblConnectionStatus.Text == "Connected")
            {
                btnConnect.Text = "Connect";
                lblConnectionStatus.Text = "Not Connected";
                //Enable textboxes
                txtDiscoveryUrl.Enabled = true;
                txtDomain.Enabled = true;
                txtPassword.Enabled = true;
                txtUserName.Enabled = true;
                //Remove data from controls
                cmbSolutions.DataSource = null;
                fileMapBindingSource.DataSource = null;
                fileMapBindingSource.List.Clear();
                //Disable few buttons
                btnLoadResourcesForSolution.Enabled = false;
                btnPublishSelected.Enabled = false;
                btnSaveMap.Enabled = false;
                btnUploadSelected.Enabled = false;
            }
            else
            {
                btnConnect.Enabled = false;

                if (string.IsNullOrEmpty(txtDiscoveryUrl.Text))
                {
                    MessageBox.Show("Organization service url is required", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    txtDiscoveryUrl.Focus();
                    return;
                }
                if (string.IsNullOrEmpty(txtUserName.Text))
                {
                    MessageBox.Show("Username is required", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    txtUserName.Focus();
                    return;
                }
                if (string.IsNullOrEmpty(txtPassword.Text))
                {
                    MessageBox.Show("Password is required", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    txtPassword.Focus();
                    return;
                }
                if (string.IsNullOrEmpty(txtDomain.Text))
                {
                    MessageBox.Show("Domain is required", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    txtDomain.Focus();
                    return;
                }

                try
                {
                    WriteMessage("Connecting to Dynamics CRM...");
                    Crm.Helper.GetServiceProxy(txtDiscoveryUrl.Text, txtUserName.Text, txtPassword.Text, txtDomain.Text);
                    Solutions = Crm.Helper.GetSolutions();
                    cmbSolutions.DataSource = null;

                    if (Solutions != null && Solutions.Count > 0)
                    {
                        cmbSolutions.DisplayMember = "FriendlyName";
                        cmbSolutions.ValueMember = "SolutionId";
                        cmbSolutions.DataSource = Solutions;
                        cmbSolutions.SelectedIndex = 0;
                        WriteMessage("Found solutions. Look at list of solutions.");
                    }
                    else
                    {
                        MessageBox.Show("Solution(s) are not available in Dynamics CRM. Cannot continue.", "Error",
                            MessageBoxButtons.OK, MessageBoxIcon.Error);
                        txtDomain.Focus();
                        return;
                    }
                    //Save new connection details to file
                    settings.BusinessServiceUrl = txtDiscoveryUrl.Text;
                    settings.Domain = txtDomain.Text;
                    settings.Password = txtPassword.Text;
                    settings.SelectedSolution = "";
                    settings.Username = txtUserName.Text;
                    settings.SaveConnection();
                    //Enable few buttons
                    btnLoadResourcesForSolution.Enabled = true;
                    btnPublishSelected.Enabled = true;
                    btnSaveMap.Enabled = true;
                    btnUploadSelected.Enabled = true;
                    btnConnect.Enabled = true;
                    //Disable textboxes
                    txtDiscoveryUrl.Enabled = false;
                    txtDomain.Enabled = false;
                    txtPassword.Enabled = false;
                    txtUserName.Enabled = false;
                    //Change label
                    lblConnectionStatus.Text = "Connected";
                    btnConnect.Text = "Change connection";
                }
                catch (Exception ex)
                {
                    btnConnect.Enabled = true;
                    WriteMessage(ex.Message);
                    MessageBox.Show(
                        "There seems to be a problem while connecting to Dynamics CRM with the information you provided."
                        + Environment.NewLine + Environment.NewLine +
                        "Please review it and try again. Error details are shown below.", "Error", MessageBoxButtons.OK,
                        MessageBoxIcon.Error);
                }
            }
        }

        private void MapAndPublishForm_Load(object sender, EventArgs e)
        {
            WriteMessage("Selected file belongs to :- " + this.ProjectPath);
            
            //Disable few buttons
            btnLoadResourcesForSolution.Enabled = false;
            btnPublishSelected.Enabled = false;
            btnSaveMap.Enabled = false;
            btnUploadSelected.Enabled = false;

            settings.SettingsFilePath = ProjectPath;
            settings.SettingsFileName = Constants.SettingsFileName;
            if (settings.LoadConnection())
            {
                txtDiscoveryUrl.Text = settings.BusinessServiceUrl;
                txtDomain.Text = settings.Domain;
                txtPassword.Text = settings.Password;
                txtUserName.Text = settings.Username;
    
                btnConnect_Click(null, null);
            }

            lblSelectedFile.Text = SelectedFileName;

            WriteMessage("Settings loaded from file");
        }

        private void btnLoadResourcesForSolution_Click(object sender, EventArgs e)
        {
            try
            {
                LoadResources();
            }
            catch (Exception ex)
            {
                WriteMessage(ex.Message);
            }
        }

        private void LoadResources()
        {
            fileMapBindingSource.DataSource = null;
            fileMapBindingSource.List.Clear();

            var webResources =
                Crm.Helper.RetrieveWebResourcesForActiveSolution((Guid)cmbSolutions.SelectedValue).ToList();

            List<FileMap> mappings = settings.LoadMappings((Guid)cmbSolutions.SelectedValue);

            settings.AddFileIfNotFound(SelectedFileName, (Guid)cmbSolutions.SelectedValue);

            Publisher publisher = Crm.Helper.GetActivePublisherForTheSolution(SelectedSolution.PublisherId.Id);

            foreach (var map in mappings)
            {
                var webResource = (from wr in webResources
                    where wr.Name == (publisher.CustomizationPrefix + "_" + map.WebResourceName)
                    select wr).FirstOrDefault();
                if (webResource != null)
                {
                    map.WebResourceDescription = webResource.Description;
                    map.WebResourceDisplayName = webResource.DisplayName;
                    map.WebResourceId = webResource.Id;
                }

                fileMapBindingSource.Add(map);
            }

            for(int i=0;i<dataGridView1.Rows.Count;i++)
            {
                if (dataGridView1.Rows[i].Cells[1].Value.ToString().Equals(SelectedFileName))
                {
                    dataGridView1.Rows[i].Selected = true;
                }
                else
                {
                    dataGridView1.Rows[i].Selected = false;
                }
            }
        }

        private void btnSaveMap_Click(object sender, EventArgs e)
        {
            settings.SaveMapping();
        }

        private void cmbSolutions_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (cmbSolutions.SelectedIndex > -1)
            {
                try
                {
                    SelectedSolution = (from s in Solutions
                        where s.SolutionId == (Guid) cmbSolutions.SelectedValue
                        select s).FirstOrDefault();

                    LoadResources();
                }
                catch (Exception ex)
                {
                    WriteMessage(ex.Message);
                }
            }
        }

        private void btnUploadSelected_Click(object sender, EventArgs e)
        {
            try
            {
                settings.SaveMapping();
                int uploadCount = 0;
                if (dataGridView1.SelectedRows != null && dataGridView1.SelectedRows.Count > 0)
                {
                    bool somethingChanged = false;
                    for (int i = 0; i < dataGridView1.SelectedRows.Count; i++)
                    {
                        var selectedRow = dataGridView1.SelectedRows[i];
                        if (selectedRow.Cells[2].Value != null && !string.IsNullOrEmpty(selectedRow.Cells[2].Value.ToString()))
                        {
                            somethingChanged = true;
                            uploadCount = CreateUpdateWebResource(selectedRow, uploadCount);
                            DateTime uploadTimestamp = DateTime.Now;
                            //selectedRow.Cells[5].Value = uploadTimestamp.ToString("yyyy-MM-dd HH:mm:ss");
                            settings.UpdateUploadDate(selectedRow.Cells[1].Value, SelectedSolution.SolutionId.Value, uploadTimestamp);
                        }
                        else
                        {
                            WriteMessage("Skipping a selected row because Web resource name is not found");
                        }
                    }

                    if (somethingChanged)
                    {
                        settings.SaveMapping();
                    }

                    if (uploadCount > 0)
                    {
                        MessageBox.Show("Uploaded " + uploadCount + " file(s)", "Success", MessageBoxButtons.OK,
                            MessageBoxIcon.Information);
                    }
                    else
                    {
                        MessageBox.Show("Did not upload any file. Look at messages for details.", "Warning", MessageBoxButtons.OK,MessageBoxIcon.Warning);
                    }
                }
                else
                {
                    MessageBox.Show("Please select at least one row and then click upload button", "Error",
                        MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }
            catch (Exception ex)
            {
                WriteMessage(ex.Message);
                MessageBox.Show("Something went wrong while uploading files to CRM. Look at messages.", "Error",
                        MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private int CreateUpdateWebResource(DataGridViewRow selectedRow, int uploadCount)
        {
            if (System.Guid.Parse(selectedRow.Cells[8].Value.ToString()).Equals(System.Guid.Empty))
            {
                Guid webResourceId = Crm.Helper.CreateWebResource(
                    filePath: ProjectPath + selectedRow.Cells[1].Value,
                    displayName: selectedRow.Cells[3].Value.ToString(),
                    description: selectedRow.Cells[4].Value.ToString(),
                    resourceName: selectedRow.Cells[2].Value.ToString(),
                    selectedsolution: SelectedSolution
                    );
                uploadCount++;
                settings.UpdateWebResourceId(selectedRow.Cells[1].Value.ToString(), SelectedSolution.Id, webResourceId);
            }
            else
            {
                Crm.Helper.UpdateWebResource(
                    filePath: ProjectPath + selectedRow.Cells[1].Value,
                    displayName: selectedRow.Cells[3].Value.ToString(),
                    description: selectedRow.Cells[4].Value.ToString(),
                    webResourceId: Guid.Parse(selectedRow.Cells[8].Value.ToString())
                    );
                uploadCount++;
            }
            return uploadCount;
        }

        private void btnPublishSelected_Click(object sender, EventArgs e)
        {
            //PublishWebResource
            try
            {
                bool somethingChanged = false;
                int uploadCount = 0;
                
                if (dataGridView1.SelectedRows != null && dataGridView1.SelectedRows.Count > 0)
                {
                    List<Guid> webResourcesToPublish = new List<Guid>();
                    for (int i = 0; i < dataGridView1.SelectedRows.Count; i++)
                    {
                        var selectedRow = dataGridView1.SelectedRows[i];
                        if (selectedRow.Cells[2].Value != null && !string.IsNullOrEmpty(selectedRow.Cells[2].Value.ToString()))
                        {
                            somethingChanged = true;
                            uploadCount = CreateUpdateWebResource(selectedRow, uploadCount);
                            webResourcesToPublish.Add(Guid.Parse(selectedRow.Cells[8].Value.ToString()));
                            DateTime uploadTimestamp = DateTime.Now;
                            settings.UpdateUploadDate(selectedRow.Cells[1].Value, SelectedSolution.SolutionId.Value, uploadTimestamp);
                        }
                        else
                        {
                            WriteMessage("Skipping a selected row because Web resource name is not found");
                        }
                    }

                    if (webResourcesToPublish.Count > 0)
                    {
                        Crm.Helper.PublishWebResource(webResourcesToPublish);
                        settings.UpdatePublishDate(webResourcesToPublish, DateTime.Now);
                    }

                    if (somethingChanged)
                    {
                        settings.SaveMapping();
                    }

                    if (uploadCount > 0)
                    {
                        MessageBox.Show("Uploaded " + uploadCount + " file(s)", "Success", MessageBoxButtons.OK,
                            MessageBoxIcon.Information);
                    }
                    else
                    {
                        MessageBox.Show("Did not upload any file. Look at messages for details.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                    }
                }
            }
            catch (Exception ex)
            {
                WriteMessage(ex.Message);
                MessageBox.Show("Something went wrong while publishing files to CRM. Look at messages.", "Error",
                        MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }


        internal void WriteMessage(string message)
        {
            if (message != null)
            {
                txtMessages.Text = DateTime.Now.ToString("hh:mm:ss fff - ") + message + Environment.NewLine + txtMessages.Text;
            }
        }

        private void dataGridView1_CellEnter(object sender, DataGridViewCellEventArgs e)
        {
            if (e.ColumnIndex == 2 && !System.Guid.Parse(dataGridView1.Rows[e.RowIndex].Cells[8].Value.ToString()).Equals(System.Guid.Empty))
            {
                dataGridView1.Rows[e.RowIndex].Cells[2].ReadOnly = true;
                WriteMessage("This file has been uploaded earlier. Cannot change webresource name.");
            }
            else if (e.ColumnIndex == 2)
            {
                dataGridView1.Rows[e.RowIndex].Cells[2].ReadOnly = false;
            }
        }

        private void linkLabel1_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            System.Diagnostics.Process.Start("http://blogs.msdn.com/b/devkeydet/archive/2013/06/19/eureka-f5-debugging-of-crm-javascript-web-resources.aspx");
        }
        
    }
}
